<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>JavaScript Loan Calculator</title>
	<script src="./common.js"></script>
	<style>
		.output{
			font-weight: bold;/* 计算结果定义为粗体 */
		}
		#payment{
			text-decoration: underline ;/* 定义：id="payment"的元素样式*/
		}
		#graph{
			border:solid black 1px;/* 图表有 1 像素的边框*/
			float: right;
		}
		th,td{
			vertical-align: top;	/* 表格单元格对齐方式为顶端对齐*/
			text-align:left;
		}
		#box{
			margin: 0px auto;
			text-align:center;
			width: 900px;
			height: 400px;
			border: 1px solid green;
			background: url(background/bj6.jpg);
		}
	</style>
</head>
<body>
<div id="box">
	<table>
		<tr>
			<th>Enter Loan Data</th>
			<td></td>
			<th>Loan Balance,Cumulative Equity,and Interest Payments</th>
		</tr>
		<tr>
			<td>Amout of the loan($):</td>
			<td><input id="amount" onchange="calculate()"></td>
			<td rowspan="8">
				<canvas id="graph" width="400" height="250"></canvas>
			</td>
		</tr>
		<tr>
			<td>Annual interest (%):</td>
			<td><input id="apr" onchange="calculate()"></td>
		</tr>
		<tr>
			<td>Repayment period (years):</td>
			<td><input id="years" onchange="calculate()"></td>
		</tr>
		<tr>
			<td>Zipcode (to find lenders):</td>
			<td><input id="zipcode" onchange="calculate()"></td>
		</tr>		
		<tr>
			<td>Approximate Payments:</td>
			<td><input type="button" onclick="calculate()" value="Calculate"></td>
		</tr>		
		<tr>
			<td>Monthly payment:</td>
			<td>$<span class="output" id="payment"></span></td>
		</tr>		
		<tr>
			<td>Total payment:</td>
			<td>$<span class="output" id="total"></span></td>
		</tr>		
		<tr>
			<td>Total interest:</td>
			<td>$<span class="output" id="totalinterest"></span></td>
		</tr>	
		<tr>
			<th>Sponsors:</th>
			<td colspan=2>
				Apply for your loan with bone of these fine lenders:
				<div id="lenders"></div>
			</td>
		</tr> 
	</table>
</div>
	<script>
		"use strict" //如果浏览器支持的话，则开启ECMAScript 5严格模式
		function calculate(){
			var amount = my$("amount");
			var apr = my$("apr");
			var years = my$("years");
			var zipcode = my$("zipcode");
			var payment = my$("payment");
			var total = my$("total");
			var totalinterest = my$("totalinterest");
		
			//假设所有的输入都是合法的，姜葱input元素中获取输入数据
			//将百分比格式转换为小数格式，并从年利率转换为月利率
			//将年度赔付转换为月度赔付		
			var principal = parseFloat(amount.value);
			var interest = parseFloat(apr.value)/100/12;
			var payments = parseFloat(years.value)*12;
			
			//现在计算月度赔付的数据
			var x = Math.pow(1 + interest,payments);//Math,pow()进行幂次运算
			var monthly = (principal * x * interest)/(x-1);

			//如果结果没有超过JavaScript 能表示的数字范围，且用户的输入也正确
			//如果所展示的结果是合法的
			if(isFinite(monthly)){
				//将数据填充至输出的字段的位置，四舍五入到小数点后两位数字
				payment.innerHTML = monthly.toFixed(2);
				total.innerHTML = (monthly * payments).toFixed(2);
				totalinterest.innerHTML = ((monthly * payments)-principal).toFixed(2);
			
				//将用户的输入数据保存下来，这样下次访问时也能取到数据
				save(amount.value,apr.Value,years.value,zipcode.value);
				//找到并展示本地放债人，但忽略网络错误
				try{
					getLenders(amount.value,apr.value,years.value,zipcode.value);
				}
				catch(e){
					console.log('异常:',e)
					/*忽略这些异常*/
				}
				//最后，用图表展示贷款余额、利息和资产受益
				chart(principal,interest,monthly,payments);
			}
			else{
				//计算结果不是数字或者无穷大，意味着输入数据是非法或者不完整的
				//清空之前的输入数据
				payment.innerHTML="";
				total.innerHTML="";				//清空元素的文本内容
				totalinterest.innerHTML="";
				chart();	//不传参的话就是清空图表
			}
		}
			
			//将用户的输入保存至localStorage对象的属性中
			//这些属性在再次访问时还会继续保持在原位置
			//如果你在浏览器中按照file：//URL 的方式直接打开本地文件，
			//则无法在某些浏览器中使用存储功能(比如Firfox)
			//而通过HTTP打开问件事可行的		
			function save(amout,apr,years,zipcode){
				if(window.localStorage){
					localStorage.loan_amount = amount;
					localStorage.loan_apr = apr;
					localStorage.loan_years = years;
					localStorage.loan_zipcode = zipcode;
				}
			}

			//在文档首次加载时，将会尝试还原输入字段
			window.onload = function(){
				//如果浏览器支持本地存储并且上次保存的值是存在的
				if(window.localStorage && localStorage.loan_amount){
					my$("amount").value = localStorage.loan_amount;
					my$("apr").value = localStorage.loan_apr;
					my$("years").value = localStorage.loan_years;
					my$("zipcode").value = localStorage.loan_zipcode;
				}
			};
			
			//将用户的输入发送至服务器端脚本（理论上）
			//将返回一个本地放贷人的链接列表，在这个例子中没有实现这种查找房贷人的服务
			//但如果改服务存在，该函数会使用它
			
			function getLenders(amount ,apr ,years,zipcode){

				//如果浏览器不支持 XMLHttpRequest 对象，则退出
 				if(!window.XMLHttpRequest) return;
				
				//找到要显示放贷人列表的元素
				if(!my$('lenders')) return; //如果返回为空则退出
				
				//将用户的输入数据进行url编码，并作为查询参数附加在url里
				var url = "getLenders.php"+ //处理数据的url地址
					"?amt = "+encodeURIComponent(amount)+
					"&apr = "+encodeURIComponent(apr)+
					"&yrs = "+encodeURIComponent(years)+
					"&zip = "+encodeURIComponent(zipcode);
				
				//通过XMLHttpRequest对象来提取返回数据
				var req = new XMLHttpRequest(); //发起一个新的请求
				req.open("GET",url);			//通过url发起一个HTTP GET请求
				req.send(null);					//不带任何正文发送这个请求
				//再返回数据之前，注册了一个事件处理函数，
				//这个处理函数将会在服务器的响应返回至客户端的时候被调用
				//这种异步编程模型在客户端的JavaScript中是非常常见的
				req.onreadystatechange = function(){
					console.log(req.readyState);
					console.log(req.status);
					if(req.readyState == 4 && req.status == 200){
						//如果代码运行到这里，说明我们得到了一个合法且完整的HTTP响应
						var response = req.responseText; //HTTP响应是以字符串的形式呈现的
						var lenders = JSON.parse(response);//将其解析为js数组

						// 将数组的放贷人对象转换为HTML字符串形式
						var list = "";
						for(var i = 0;i<lenders.length;i++){
							list +="<li><a href = '"+lenders[i].url+"'>"+lenders[i].name+"</a>";
						}
						
						//将数据在HTML元素中呈现出来
						ad.innerHTML = "<ul>"+list+"</ul>";
					}
				}
			}

			//在HTML<canvas>元素中用图表展示月度贷款余额，利息和资产受益
			//如果不传入参数的话，这清空之前的图表数据
			function chart(principal,interest,monthly,payments){
				var graph = my$("graph");//得到<canvas>标签
				graph.width = graph.width //用一种巧妙的手法清除并重置画布
				
				//如果不传入参数， 或者浏览器不支持画布，则直接返回
				if(arguments.length == 0 || !graph.getContext)return;
				
				//获得画布元素的“Conrtext”对象，这个对象定义了一组绘画AP1
				var g = graph.getContext("2d");		//所有的绘画操作都将基于这个对象
				var width = graph.width,
					height = graph.height;			//获得画布大小
				
				//这里的函数作用是将付款数字和美元数据转换为像素
				function paymentToX(n){
					return n * width / payments;
				}
				function amountToY(a){
					return  height - (a * height / (monthly * payments * 1.05));
				}
				//付款数据是一条从（0，0）到 （payments , monthly * payments）的直线
				g.moveTo(paymentToX(0),amountToY(0));		//从左下方开始
				g.lineTo(paymentToX(payments),amountToY(monthly * payments));//绘至右上方
				g.lineTo(paymentToX(payments),amountToY(0));	//再至右下方
				g.closePath();		//将结尾连接至开头
				g.fillStyle = "#f88"; 	//亮红色
				g.fill();	//填充矩形
				g.font = "bold 12px sans-serif";	//定义一种字体
				g.fillText("Total Interest Payments",20,20);	//将文字绘制到图例中
			
				//很多资产数据并不是线性的，很难将其反映至图表中
				var equiyty = 0;
				g.beginPath();		//开始绘制新图形
				g.moveTo(paymentToX(0),amountToY(0)); //从左下方开始
				for(var p = 1; p < payments ; p++ ){
					//计算出每一笔赔付的利息
					var thisMonthInterest = (principal - equiyty) * interest;
					equiyty += (monthly - thisMonthInterest); //得到资产额
					g.lineTo(paymentToX(p),amountToY(equiyty)); //将数据绘制到画布上
							 
				}
				g.lineTo(paymentToX(payments),amountToY(0));//将数据线绘制至x轴
				g.closePath();//将线条结尾链接至线条开头
				g.fillStyle="green"; //使用绿色绘制图形
				g.fill();	//曲线之下的部分均填充
				g.fillText("Total Equity",20,35)	//文本颜色设置为绿色
				
				//再次循环，余额数据会显示为黑色粗线条
				var bal = principal;
				g.beginPath();
				g.moveTo(paymentToX(0),amountToY(bal));
				for(var p = 1; p <= payments ; p++){
					var thisMonthsInterest = bal * interest;
					bal -= (monthly - thisMonthsInterest);		//得到资产额
					g.lineTo(paymentToX(p),amountToY(bal)); 	//将直线连接至某点
				}
				g.lineWidth = 3 		//将直线宽度加粗
				g.stroke();				//绘制余额的曲线
				g.fillStyle = "black" 	//使用黑色字体
				g.fillText("Loan Balance",20,50) //图例文字
				
				//将年度数据在x轴做标记
				g.textAlign = "center";
				var y = amountToY(0);
				for (var year = 1; year * 2 <= payments;year++){
					var x=paymentToX(year * 12);
					g.fillRect(x-0.5,y-3,1,3);
					if(year == 1) {
						g.fillText("Year",x,y-5);
						}		
					if(year % 5 == 0 && year * 12 !==payments){
						g.fillText(String(year),x,y-5);
					}
				}
			
				//将赔付数额标记在右边界
				g.textAlign = "right";		//文字右对齐
				g.textBaseline = "middle";	//文字垂直居中
				var ticks = [monthly * payments,principal];
				var rightEdge = paymentToX(payments);
				for( var i = 0 ; i < ticks.length ;i++){
					var  y = amountToY(ticks[i]);
					g.fillRect(rightEdge - 3,y - 0.5,3,1);
					g.fillText(String(ticks[1].toFixed(0)),rightEdge-5,y)
				}	
			
			}

		
	</script>
</body>
</html>